/*
 * xAPBSCoutput.java
 *
 * xAP BSC input element for MyOpenLab
 *
 * 03/11/09 by Daniel Berenguer : first version
 */

import VisualLogic.*;
import VisualLogic.variables.*;
import tools.*;

import xAP.drvCore;
import xAP.xAPtypes.TypeOfElement;
import xAP.xAPBSCtext;
import xAP.xAPBSCendpoint;
import xAP.xAPBSClevel;
import xAP.xAPBSCstate;
import xAP.xAPdialog;

import java.awt.*;
import java.util.ArrayList;


/********************************************************************************************
 * xAPBSCoutput class
 *********************************************************************************************/
public class xAPBSCoutput extends JVSMain implements MyOpenLabDriverOwnerIF
{
    private Image image;
    private VSObject input;
    private MyOpenLabDriverIF driver ;
    private int dType = -1;
    private VSComboBox dtPin = new VSComboBox();
    private String strDataTypes[] = {"C_BOOLEAN", "C_BYTE", "C_INTEGER", "C_DOUBLE", "C_STRING"};
    private int intDataTypes[] = {element.C_BOOLEAN, element.C_BYTE, element.C_INTEGER, element.C_DOUBLE, element.C_STRING};
    private xAPBSCendpoint bscEndpoint;
    private VSPropertyDialog xAPdialog = new VSPropertyDialog();
    private VSString xAPsourceAddr = new VSString();

   /********************************************************************************************
    * getCommand
    *
    * Receive command from xAP driver
    *
    ********************************************************************************************/
    @Override
    public void getCommand(String commando, Object value)
    {
        // Command received from xAP driver
    }

   /********************************************************************************************
    * xPaint
    *
    * Graphical stuff
    *
    ********************************************************************************************/
    @Override
    public void xpaint(java.awt.Graphics g)
    {
        drawImageCentred(g,image);
    }

   /********************************************************************************************
    * onDispose
    *
    * Refreshes
    *
    ********************************************************************************************/
    @Override
    public void onDispose()
    {
        if (image!=null)
        {
            image.flush();
            image=null;
        }
    }

   /********************************************************************************************
    * init
    *
    * Initialization
    *
    ********************************************************************************************/
    @Override
    public void init()
    {
        initPins(0,0,0,1);
        setSize(63, 22);

        element.jSetInnerBorderVisibility(false);
        element.jSetTopPinsVisible(false);
        element.jSetBottomPinsVisible(false);
        element.jSetRightPinsVisible(false);
        image = element.jLoadImage(element.jGetSourcePath()+"icon.gif");

        setPin(0, element.C_BOOLEAN, element.PIN_INPUT);
        element.jSetPinDescription(0,"BSC output");

        // Fill data types
        int i;
        for(i=0 ; i<strDataTypes.length ; i++)
            dtPin.addItem(strDataTypes[i]);
        dtPin.selectedIndex = 0;

        if (dType > -1)
        {
            dtPin.selectedIndex = dType;
        }

        element.jSetResizable(false);
        element.jSetCaptionVisible(true);
        element.jSetCaption("x");
        setName("xAP_BSC_output");
    }

   /********************************************************************************************
    * initInputPins
    *
    * Setup input pins
    *
    ********************************************************************************************/
    @Override
    public void initInputPins()
    {
        input = (VSObject)element.getPinInputReference(0);
    }

   /********************************************************************************************
    * start
    *
    * Start simulation
    *
    ********************************************************************************************/
    @Override
    public void start()
    {
        ArrayList args = new ArrayList();

        String strSource = xAPsourceAddr.getValue();
        // Send xAP source address
        args.add(strSource);

        // Send type of output
        if (input instanceof VSBoolean)
            args.add(TypeOfElement.BSC_OUTPUT_STA);
        else
            args.add(TypeOfElement.BSC_OUTPUT_NUM);
        
        // Open xAP driver
        driver = element.jOpenDriver("MyOpenLab.xAP", args);
        driver.registerOwner(this);
    }

   /********************************************************************************************
    * setPropertyEditor
    *
    * Add new controls to the Property editor window
    *
    ********************************************************************************************/
    @Override
    public void setPropertyEditor()
    {
        element.jAddPEItem("Data type", dtPin, 0,0);
        element.jAddPEItem("xAP source", xAPdialog, 0,0);
    }

   /********************************************************************************************
    * propertyChanged
    *
    * Method called whenever a property from the Property editor window changes
    *
    ********************************************************************************************/
    @Override
    public void propertyChanged(Object o)
    {
        if (o.equals(dtPin))
            setDataType();

        element.jRepaint();
    }

   /********************************************************************************************
    * openPropertyDialog
    *
    * Open xAP property dialog
    *
    ********************************************************************************************/
    @Override
    public void openPropertyDialog()
    {
        xAPdialog frm = new xAPdialog(TypeOfElement.BSC_OUTPUT_NUM);
        frm.setModal(true);
        frm.setVisible(true);

        if (frm.getResult())
        {
            // Set source address
            String strSourceAddr = frm.getSourceAddr();
            xAPsourceAddr.setValue(strSourceAddr);
            xAPdialog.setText(strSourceAddr);
        }

        element.jRepaint();
    }

   /********************************************************************************************
    * loadFromStream
    *
    * Load properties
    *
    ********************************************************************************************/
    @Override
    public void loadFromStream(java.io.FileInputStream fis)
    {
        try
        {
            dtPin.loadFromStream(fis);
            setDataType();
            xAPsourceAddr.loadFromStream(fis);
            setSourceAddress();
            element.jRepaint();
        } catch (Exception ex){  }
    }

   /********************************************************************************************
    * saveToStream
    *
    * Save properties
    *
    ********************************************************************************************/
    @Override
    public void saveToStream(java.io.FileOutputStream fos)
    {
        dtPin.saveToStream(fos);
        xAPsourceAddr.saveToStream(fos);
    }

   /********************************************************************************************
    * setDataType
    *
    * Set data type for the xAP element
    *
    ********************************************************************************************/
    public void setDataType()
    {
        dType = intDataTypes[dtPin.selectedIndex];
        setPin(0, dType, element.PIN_INPUT);
    }

   /********************************************************************************************
    * setSourceAddress
    *
    * Set xAP source address for tue current element
    *
    ********************************************************************************************/
    public void setSourceAddress()
    {
        String Source = xAPsourceAddr.getValue();
        xAPdialog.setText(Source);
    }

   /********************************************************************************************
    * process
    *
    * Process input signal
    *
    ********************************************************************************************/
    @Override
    public void process()
    {
        String strSource = xAPsourceAddr.getValue();
        // Get endpoint from global table
        bscEndpoint = drvCore.bscEndpoints.getEndpointFromSource(strSource);

        // Only if the endpoint exists in the network
        if (bscEndpoint != null)
        {
            // Binary endpoint
            if (input instanceof VSBoolean)
            {
                xAPBSCstate bscState = null;

                VSBoolean val = (VSBoolean)input;
                if (val.getValue() == true)
                    bscState = new xAPBSCstate("ON");
                else
                    bscState = new xAPBSCstate("OFF");

                // Only if the state is going to change
                if (bscEndpoint.state.toBool() != bscState.toBool())
                {
                    // Send BSC command
                    bscEndpoint.sendCommand(bscState);
                }
            }
            // BSC level endpoint
            else if (bscEndpoint.level != null)
            {
                long lTotal = bscEndpoint.level.getTotal();
                xAPBSClevel bscLevel = new xAPBSClevel("0/"+lTotal);

                if (input instanceof VSString)
                {
                    VSString val = (VSString)input;
                    bscLevel = new xAPBSClevel(val.getValue());
                }
                else if (input instanceof VSDouble)
                {
                    VSDouble val = (VSDouble)input;
                    bscLevel.updateFromValue(val.getValue());
                }
                else if (input instanceof VSInteger)
                {
                    VSInteger val = (VSInteger)input;
                    bscLevel.updateFromValue(val.getValue());
                }
                else if (input instanceof VSByte)
                {
                    VSByte val = (VSByte)input;
                    bscLevel.updateFromValue(val.getValue());
                }
                else
                    return;

                // Only if the BSC level has changed
                if (bscEndpoint.level.toString().compareTo(bscLevel.toString()) != 0)
                {
                    // Send BSC command
                    bscEndpoint.sendCommand(bscLevel);
                }
            }
            // BSC text endpoint
            else
            {
                // Clone current BSC level
                xAPBSCtext bscText = null;

                if (input instanceof VSString)
                {
                    VSString val = (VSString)input;
                    bscText = new xAPBSCtext(val.getValue());
                }
                else if (input instanceof VSDouble)
                {
                    VSDouble val = (VSDouble)input;
                    double dblVal = val.getValue();
                    bscText = new xAPBSCtext(Double.toString(dblVal));
                }
                else if (input instanceof VSInteger)
                {
                    VSInteger val = (VSInteger)input;
                    int intVal = val.getValue();
                    bscText = new xAPBSCtext(Integer.toString(intVal));
                }
                else if (input instanceof VSByte)
                {
                    VSByte val = (VSByte)input;
                    byte btVal = val.getValue();
                    bscText = new xAPBSCtext(Byte.toString(btVal));
                }
                else
                    return;

                // Only if the BSC text field has changed since the send of the last command
                if (bscText.toString().compareTo(bscEndpoint.text.toString()) != 0)
                {
                    // Send BSC command
                    bscEndpoint.sendCommand(bscText);
                }
            }
        }
    }
}
